"""
Maintains "Manage bookmarks" dialog.
"""

import pygtk
import gtk
import gobject

from .. import exceptions
from .. import path
from .. import settings
from .. import plugin
from .. import bookmarks
from .. import strunicode as su

parent = None

def initialize(parent_window):
    """
    Initialize module, parent_window must point to main application window
    """
    global parent

    if not parent is None:
        raise exceptions.InitializationError("Module already initialized!")
    
    parent = parent_window

def assert_initialized():
    if parent is None:
        raise exceptions.GuiException("Module 'preferences' is not initialized!")

ITEM_TYPE_FOLDER = 1
ITEM_TYPE_BOOKMARK = 2 
iw = gtk.Invisible()
FOLDER_PIXBUF = iw.render_icon(gtk.STOCK_OPEN, gtk.ICON_SIZE_MENU)
BOOKMARK_PIXBUF = iw.render_icon(gtk.STOCK_APPLY, gtk.ICON_SIZE_MENU)

def run_dualog():
    """
    Create an display bookmarks management window
    """
    assert_initialized()
    xml = gtk.glade.XML(path.get_data_path("pybookshelf.glade"), root="manage_bookmarks_dialog",
                        domain="pybookshelf")
    dialog = xml.get_widget("manage_bookmarks_dialog")
    dialog.set_transient_for(parent)
    treeview = xml.get_widget("bookmarks_tree")

    dialog.connect("configure_event", on_resize, "manage_bookmarks")
    treeview.connect("drag-drop", on_drag_drop)
    treeview.connect("cursor-changed", on_cursor_changed, xml)
    xml.get_widget("hpaned1").connect("notify::position", on_splitter_move, "manage_bookmarks")
    xml.get_widget("add_new_folder_button").connect("clicked", on_add_new_folder, treeview)
    xml.get_widget("remove_item_button").connect("clicked", on_delete_item, treeview, xml)
    xml.get_widget("bookmark_title_entry").connect("changed", on_title_entry_changed, treeview)
    xml.get_widget("group_title_entry").connect("changed", on_title_entry_changed, treeview)
    

    # fill treeview with folders and bookmarks
    treestore = gtk.TreeStore(gtk.gdk.Pixbuf, gobject.TYPE_STRING, gobject.TYPE_INT, gobject.TYPE_LONG, gobject.TYPE_STRING)
    #p = treestore.append(None, [folder_icon_pb, "as", True])
    #treestore.append(p, [bookmark_icon_pb, "abyrvalg", False])
    #treestore.append(None, [bookmark_icon_pb, "as adasdasdas", False])
    groups = bookmarks.get_bookmark_groups(-1)
    groups_map = populate_treestore(treestore, None, groups)
    
    for id, target, title, bookmark_group_id in bookmarks.get_all_bookmarks():
        folder_iter = None
        if bookmark_group_id in groups_map:
            folder_iter = groups_map[bookmark_group_id]
            
        treestore.append(folder_iter, [BOOKMARK_PIXBUF, title, ITEM_TYPE_BOOKMARK, id, target])

    
    tvcolumn = gtk.TreeViewColumn("")
    treeview.append_column(tvcolumn)
    cell = gtk.CellRendererPixbuf()
    tvcolumn.pack_start(cell, False)
    tvcolumn.set_alignment(0)
    tvcolumn.add_attribute(cell, 'pixbuf', 0)

    cell = gtk.CellRendererText()
    #cell.set_property("xpad", 0)
    tvcolumn.pack_end(cell, False)
    tvcolumn.set_alignment(0)
    tvcolumn.add_attribute(cell, 'text', 1)

    
    treeview.set_model(treestore)
    # connect signal after filling the model to avoid initial model population processing
    treestore.connect("row-changed", on_row_changed, treeview)
    treeview.expand_all()

    settings.restore_window_geometry(dialog, "manage_bookmarks")
    xml.get_widget("hpaned1").set_position(settings.get_int("manage_bookmarks_splitter_pos"))
    [xml.get_widget(x).hide_all() for x in ["empty_props_widget", "folder_props_widget", "bookmark_props_widget"] ]
    
    response = dialog.run()
    
    if response == 1:
        # build new bookmark groups tree
        def scan_treestore_groups(first_iter):
            """
            Scan treestore
            
            @return: list_of_subgroups
            """
            iter = first_iter
            subgroups = []
            # subgroup is (subgroup_iter, LIST)
            
            while True:
                if iter is None: 
                    break
                
                item_type = treestore.get_value(iter, 2)
                if item_type == ITEM_TYPE_FOLDER:
                    #row = treestore.get(iter, 0, 1, 2, 3, 4)
                    subgroups.append( (iter, scan_treestore_groups(treestore.iter_children(iter))) )
                
                iter = treestore.iter_next(iter)
                
            return subgroups
        
        groups = scan_treestore_groups(treestore.get_iter_first())

        # form groups tree
        def form_groups_tree(groups):
            # each item is [group_title, group_folder_iter, subgroups_list]
            groups_tree = []
            
            for iter, subgroups in groups:
                title = su.ustr2unicode(treestore.get_value(iter, 1))
                subgroups = form_groups_tree(subgroups)
                groups_tree.append([title, -1, iter, subgroups])
                
            return groups_tree
                
        groups_tree = bookmarks.recreate_bookmark_groups(form_groups_tree(groups))
        
        # recreate bookmarks
        def form_bookmark_list(groups):
            bookmark_list = []
            
            for group_title, group_id, iter, subgroups in groups:
                cur_iter = treestore.iter_children(iter)
                
                while True:
                    if cur_iter is None:
                        break
                    
                    b_title, item_type, target = treestore.get(cur_iter, 1, 2, 4)
                    if item_type == ITEM_TYPE_BOOKMARK:
                        bookmark_list.append( (su.ustr2unicode(target), su.ustr2unicode(b_title), group_id) )
                        
                    cur_iter = treestore.iter_next(cur_iter) 
                    
                bookmark_list += form_bookmark_list(subgroups)
                
            return bookmark_list
        
        bookmark_list = form_bookmark_list([ ["", -1, None, groups_tree] ])
        bookmarks.add_many(bookmark_list, replace=True)
        bookmarks.get_notifier().emit_bookmarks_changed_signal()
        
    dialog.destroy()
    
def populate_treestore(treestore, parent_folder, groups):
    """
    Populate treestore object with folders-groups.
    
    @return: dict where key is group_id and value is corresponding folder gtk.TreeIter instance
    """
    groups_map = dict()
    for group_id, group_title, subgroups in groups:
        p = treestore.append(parent_folder, [FOLDER_PIXBUF, group_title, ITEM_TYPE_FOLDER, group_id, ""])
        groups_map[group_id] = p
        submap = populate_treestore(treestore, p, subgroups)
        for k,v in submap.iteritems():
            groups_map[k] = v
            
    return groups_map


    
def on_resize(dialog, event, settings_prefix):
    settings.remember_window_geometry(dialog, settings_prefix)

def on_splitter_move(hpaned, event, settings_prefix):
    pos = hpaned.get_position()
    settings.set_int(settings_prefix + "_splitter_pos", pos)

def on_drag_drop(treeview, context, x, y, etime):
    drop_info = treeview.get_dest_row_at_pos(x, y)
    # get selected row in the treeview
    if drop_info:
        model = treeview.get_model()
        path, position = drop_info
        cur_path, cf = treeview.get_cursor()
        drag_item_type =  model.get_value(model.get_iter(cur_path), 2)
        item_type = model.get_value(model.get_iter(path), 2)
        if (position == gtk.TREE_VIEW_DROP_BEFORE and item_type == ITEM_TYPE_FOLDER 
            and drag_item_type == ITEM_TYPE_BOOKMARK):
            # reject drop: bookmark before folder
            return True
        
        if (position == gtk.TREE_VIEW_DROP_AFTER and item_type == ITEM_TYPE_BOOKMARK
            and drag_item_type == ITEM_TYPE_FOLDER):
            # reject drop: folder after bookmark
            return True
        
        if (position == gtk.TREE_VIEW_DROP_BEFORE 
            or  position == gtk.TREE_VIEW_DROP_AFTER
            or item_type == ITEM_TYPE_FOLDER):
            # accept drop
            return False

    return True

def on_row_changed(treestore, path, iter, treeview):
    treeview.expand_all()
    
def on_cursor_changed(treeview, xml):
    # hide all panes
    [xml.get_widget(x).hide_all() for x in ["empty_props_widget", "folder_props_widget", "bookmark_props_widget"] ]

    model = treeview.get_model()
    cur_path, cf = treeview.get_cursor()
    if cur_path is None:
        return
    
    iter = model.get_iter(cur_path)
    item_type =  model.get_value(iter, 2)
    
    if item_type == ITEM_TYPE_BOOKMARK:
        xml.get_widget("bookmark_props_widget").show_all()
        title_entry = xml.get_widget("bookmark_title_entry")
        target_entry = xml.get_widget("bookmark_target_entry")

        title_entry.set_text(model.get_value(iter, 1))
        target_entry.set_text(model.get_value(iter, 4))
        title_entry.grab_focus()
    elif item_type == ITEM_TYPE_FOLDER:
        xml.get_widget("folder_props_widget").show_all()
        title_entry = xml.get_widget("group_title_entry")
        
        title_entry.set_text(model.get_value(iter, 1))
        title_entry.grab_focus()
    else:
        xml.get_widget("empty_props_widget").show_all()

def on_add_new_folder(button, treeview):
    """
    Add new folder at the beginning of tree
    """
    model = treeview.get_model()
    model.prepend(None, [FOLDER_PIXBUF, _("New Folder"), ITEM_TYPE_FOLDER, -1, ""])
    # focus just added row
    treeview.set_cursor((0,))
    
def on_delete_item(button, treeview, xml):
    model = treeview.get_model()
    cur_path, cf = treeview.get_cursor()
    
    if cur_path is None:
        return
    
    model.remove(model.get_iter(cur_path))
    on_cursor_changed(treeview, xml)
 
def on_title_entry_changed(entry, treeview):
    model = treeview.get_model()
    cur_path, cf = treeview.get_cursor()
    iter = model.get_iter(cur_path)
    model.set_value(iter, 1, entry.get_text())
        
            
            
            
            
            
            
            
            
